/*
* Conditions Of Use 
* 
* This software was developed by employees of the National Institute of
* Standards and Technology (NIST), an agency of the Federal Government.
* Pursuant to title 15 Untied States Code Section 105, works of NIST
* employees are not subject to copyright protection in the United States
* and are considered to be in the public domain.  As a result, a formal
* license is not needed to use the software.
* 
* This software is provided by NIST as a service and is expressly
* provided "AS IS."  NIST MAKES NO WARRANTY OF ANY KIND, EXPRESS, IMPLIED
* OR STATUTORY, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTY OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, NON-INFRINGEMENT
* AND DATA ACCURACY.  NIST does not warrant or make any representations
* regarding the use of the software or the results thereof, including but
* not limited to the correctness, accuracy, reliability or usefulness of
* the software.
* 
* Permission to use this software is contingent upon your acceptance
* of the terms of this agreement
*  
* .
* 
*/
package gov.nist.javax.sip.parser;

import gov.nist.core.Token;
import gov.nist.javax.sip.header.*;
import java.text.ParseException;

/**
 * Parser for UserAgent header.
 * 
 * @version 1.2 $Revision: 1.14 $ $Date: 2008/07/30 14:36:07 $
 * 
 * @author Olivier Deruelle  <br/>
 * @author M. Ranganathan  <br/>
 * 
 * 
 */
public class UserAgentParser extends HeaderParser {

	/**
	 * Constructor
	 * 
	 * @param userAgent -
	 *            UserAgent header to parse
	 */
	public UserAgentParser(String userAgent) {
		super(userAgent);
	}

	/**
	 * Constructor
	 * 
	 * @param lexer -
	 *            the lexer to use.
	 */
	protected UserAgentParser(Lexer lexer) {
		super(lexer);
	}

	/**
	 * parse the message. Note that we have losened up on the parsing quite a bit because 
	 * user agents tend to be very bad about specifying the user agent according to RFC.
	 * 
	 * @return SIPHeader (UserAgent object)
	 * @throws SIPParseException
	 *             if the message does not respect the spec.
	 */
	public SIPHeader parse() throws ParseException {
		if (debug)
			dbg_enter("UserAgentParser.parse");
		UserAgent userAgent = new UserAgent();
		try {
			headerName(TokenTypes.USER_AGENT);
			if (this.lexer.lookAhead(0) == '\n')
				throw createParseException("empty header");

			/*
			 * BNF User-Agent = "User-Agent" HCOLON server-val *(LWS server-val)
			 * server-val = product / comment product = token [SLASH
			 * product-version] product-version = token
			 */
			while (this.lexer.lookAhead(0) != '\n'
					&& this.lexer.lookAhead(0) != '\0') {

				if (this.lexer.lookAhead(0) == '(') {
					String comment = this.lexer.comment();
					userAgent.addProductToken('(' + comment + ')');
				} else {
					// product = token [SLASHproduct-version]
					// product-version = token
					//	The RFC Does NOT allow this space but we are generous in what we accept 
					
					this.getLexer().SPorHT();
					
				
					String product = this.lexer.byteStringNoSlash();
					if ( product == null ) throw createParseException("Expected product string");
					
					StringBuffer productSb = new StringBuffer(product);
					// do we possibily have the optional product-version?
					if (this.lexer.peekNextToken().getTokenType() == TokenTypes.SLASH) {
						// yes
						this.lexer.match(TokenTypes.SLASH);
						// product-version
						// The RFC Does NOT allow this space but we are generous in what we accept 
						this.getLexer().SPorHT();
						
						String productVersion = this.lexer.byteStringNoSlash();
						
						if ( productVersion == null ) throw createParseException("Expected product version");
						
						productSb.append("/");

						productSb.append(productVersion);
					}

					userAgent.addProductToken(productSb.toString());
				}
				// LWS
				this.lexer.SPorHT();
			}
		} finally {
			if (debug)
				dbg_leave("UserAgentParser.parse");
		}

		return userAgent;
	}

	
	  public static void main(String args[]) throws ParseException { String
	  userAgent[] = { "User-Agent: Softphone/Beta1.5 \n", "User-Agent:Nist/Beta1 (beta version) \n", "User-Agent: Nist UA (beta version)\n",
	  "User-Agent: Nist1.0/Beta2 Ubi/vers.1.0 (very cool) \n" , 
	  "User-Agent: SJphone/1.60.299a/L (SJ Labs)\n",
	  "User-Agent: sipXecs/3.5.11 sipXecs/sipxbridge (Linux)\n"};
	  
	  for (int i = 0; i < userAgent.length; i++ ) { UserAgentParser parser =
	  new UserAgentParser(userAgent[i]); UserAgent ua= (UserAgent)
	  parser.parse(); System.out.println("encoded = " + ua.encode()); }
	   }
	 
}
